/* pfx2john utility, written in June of 2012 by Dhiru Kholia.
 *
 * This software is Copyright (c) 212, Dhiru Kholia <dhiru.kholia at gmail.com>
 * and it is hereby released under GPL.

 * pfx2john is based on crackpkcs12. crackpkcs12 is a multithreaded program
 * to crack PKCS12 files.
 * Copyright (C) 2011, 2012 Alfredo Esteban de la Torre
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU General Public License in all respects
 *  for all of the code used other than OpenSSL.  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so.  If you
 *  do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 * Usage:
 *
 * 1. Run pfx2john on .pfx / .p12p file(s) as "pfx2john [.pfx / .p12  file(s)]". Output
 *    is written to standard output.
 * 2. Run JtR on the output generated by pfx2john as "john [output file]".
 *
 * Notes:
 *
 * Output Line Format: filename:$pfx$*file-length*hex-encoding-of-entire-file-contents
 *
 * Compile: gcc -Wall pfx2john.c -lcrypto -lssl common.o -o ../run/pfx2john */

#include "arch.h"

#if !AC_BUILT || HAVE_BIO_NEW

#include <stdio.h>
#include <stdlib.h>
#if !AC_BUILT || HAVE_LIMITS_H
#include <limits.h>
#endif
#include <errno.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/bio.h>
#include <openssl/pkcs12.h>
#include <openssl/ssl.h>
#include "jumbo.h"
#include "common.h"
#include "arch.h"
#include "params.h"
#include "memdbg.h"

static void process_file(const char *filename)
{
	FILE *pfxfile;
	int i, count;
	unsigned char buffer[0x30000]; // was LINE_BUFFER_SIZE, fixme!
	BIO* in = NULL;
	PKCS12 *p12 = NULL;
	const char *ext[] = {".p12",".pfx"};
	char *fname;

	if (!(pfxfile = fopen(filename, "rb"))) {
	    fprintf(stderr, "! %s : %s\n", filename, strerror(errno));
	    return;
	}
	in = BIO_new_file(filename, "rb");
	if (!in) {
		fprintf (stderr, "PKCS12 file not found: %s\n", filename);
		fclose(pfxfile);
		return;
	}
	if(!(p12 = d2i_PKCS12_bio (in, NULL))) {
		perror("Unable to create PKCS12 object\n");
		fclose(pfxfile);
	    	return;
	}
	if(PKCS12_verify_mac(p12, "", -1)) {
		fprintf(stderr, "%s has no password!\n", filename);
		fclose(pfxfile);
		return;
	}
	count = fread(buffer, 1, sizeof(buffer), pfxfile);
	fname = strip_suffixes(basename(filename), ext, 2);
	printf("%s:$pfx$*%d*", fname, count);
	for (i = 0; i < count; i++) {
	    printf("%c%c", itoa16[ARCH_INDEX(buffer[i] >> 4)],
	            itoa16[ARCH_INDEX(buffer[i] & 0x0f)]);
	}
	printf("\n");
	fclose(pfxfile);
	if(in)
		BIO_free(in);
}

int pfx2john(int argc, char **argv)
{
	int i;

	/* OpenSSL init, cleanup part is left to OS */
	SSL_load_error_strings();
	SSL_library_init();
	OpenSSL_add_all_algorithms();

	if (argc < 2) {
		puts("Usage: pfx2john [.pfx / .p12 file(s)]");
		return 0;
	}

	for (i = 1; i < argc; i++)
	    process_file(argv[i]);

	return 0;
}

#endif
